﻿using Microsoft.Win32;
using MyApp.Models;
using MyApp.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace MyApp
{
  public enum ExitCode
  {
    SUCCESS,
    WARNING,
    FAIL
  }
  class Program
  {
    [STAThread]
    static int Main(string[] args)
    {
      int exitCode = -1;
      try
      {
        //注： 在这里不要有任何Console.WriteLine, 否则会影响读取OpenStandardInput， OpenStandardOutput
        EventMessage em = ParseEventMessage(args);
        int result = exitCode = ProcessMessage(em);
        //返回事件
        if (IsChromeEvent(args))
        {
          Output4Chrome(result, em);
        }
        else
        {
          Output4Firefox(result.ToString());
        }
      }
      catch (Exception e)
      {
        LogMessage(e.StackTrace);
        Console.WriteLine(e.StackTrace);
        return exitCode;
      }
      return exitCode;
    }    
    static int ProcessMessage(EventMessage em)
    {
      ExitCode ec = ExitCode.FAIL;
      if (em == null) return (int)ec;
      ScreenShareBusiness ssb = new ScreenShareBusiness();
      switch (em.Action)
      {
        case ActionConst.START:
          ssb.StartProcess();
          ec = ExitCode.SUCCESS;
          break;
        case ActionConst.STOP:
          ssb.StopProcess();
          ec = ExitCode.SUCCESS;
          break;
        case ActionConst.QUERY:
          bool status = ssb.IsRunning();
          ec = status ? ExitCode.SUCCESS : ExitCode.FAIL;
          break;
        default:
          ec = ExitCode.FAIL;
          break;
      }
      return (int)ec;
    }
    static bool IsChromeEvent(string[] args)
    {
      if (args.Length != 0)
      {
        return args[0].ToLower().Contains("parent-window");
      }
      return false;
    }
    static EventMessage ParseEventMessage(string[] args)
    {
      string message = string.Empty;
      if (args.Length != 0)
      {
        if (IsChromeEvent(args)) /*Chrome plugin will post this args*/
        {
          message = OpenStandardStreamIn();
          message = message.Replace("\\","");
          message = message.Trim('"');
        }
        else /*Firefox cmd parameter*/
        {
          message = args[0];
        }
      }
      LogMessage(message);
      return JsonUtils.JsonDeserialize<EventMessage>(message);
    }
    static string OpenStandardStreamIn()
    {
      //// We need to read first 4 bytes for length information
      Stream stdin = Console.OpenStandardInput();

      int length = 0;
      byte[] bytes = new byte[4];
      stdin.Read(bytes, 0, 4);
      length = System.BitConverter.ToInt32(bytes, 0);

      string input = "";
      for (int i = 0; i < length; i++)
      {
        input += (char)stdin.ReadByte();
      }

      return input;
    }
    static void Output4Chrome(int exitCode, EventMessage em)
    {
      OutputMessage output = new OutputMessage();
      output.Type = em.Type;
      output.ExitCode = exitCode;
      output.Output = "Success";
      OpenStandardOutput(JsonUtils.JsonSerializer(output));
    }
    static void OpenStandardOutput(string returnMessage)
    {
      var bytes = System.Text.Encoding.UTF8.GetBytes(returnMessage);
      var stdout = Console.OpenStandardOutput();
      stdout.WriteByte((byte)((returnMessage.Length >> 0) & 0xFF));
      stdout.WriteByte((byte)((returnMessage.Length >> 8) & 0xFF));
      stdout.WriteByte((byte)((returnMessage.Length >> 16) & 0xFF));
      stdout.WriteByte((byte)((returnMessage.Length >> 24) & 0xFF));
      stdout.Write(bytes, 0, bytes.Length);
      stdout.Flush();
    }
    static void LogMessage(object msg)
    {
      string now = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
      AppendLogMessage(now + " => " + msg.ToString() + "\r\n");
    }
    static void AppendLogMessage(string content)
    {
      string logfile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log.txt");
      FileStream fs = null;
      Encoding encoder = Encoding.UTF8;
      byte[] bytes = encoder.GetBytes(content);
      try
      {
        fs = File.OpenWrite(logfile);
        fs.Position = fs.Length;
        fs.Write(bytes, 0, bytes.Length);
      }
      catch (Exception ex)
      {
        Console.WriteLine("Write log file error: {0}", ex.ToString());
      }
      finally
      {
        fs.Close();
      }
    }
    static void Output4Firefox(string exitCode)
    {
      string outputfile = Path.Combine(System.Environment.GetEnvironmentVariable("TEMP"), "screenshare.tmp");
      if (File.Exists(outputfile)) File.Delete(outputfile);
      FileStream fs = null;
      Encoding encoder = Encoding.UTF8;
      byte[] bytes = encoder.GetBytes(exitCode);
      try
      {
        fs = File.OpenWrite(outputfile);
        fs.Position = fs.Length;
        fs.Write(bytes, 0, bytes.Length);
      }
      catch (Exception ex)
      {
        Console.WriteLine("Write log file error: {0}", ex.ToString());
      }
      finally
      {
        fs.Close();
      }
    }
  }

}
